package com.train.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.train.user.domain.UserPlan;
import com.train.user.domain.UserPlanItem;
import com.train.user.domain.UserPlanProgress;
import com.train.user.dto.PlanProgressDTO;
import com.train.user.mapper.UserPlanItemMapper;
import com.train.user.mapper.UserPlanMapper;
import com.train.user.mapper.UserPlanProgressMapper;
import com.train.user.service.UserPlanProgressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserPlanProgressServiceImpl extends ServiceImpl<UserPlanProgressMapper, UserPlanProgress>
        implements UserPlanProgressService {
    @Autowired
    UserPlanProgressMapper userPlanProgressMapper;
    @Autowired
    UserPlanItemMapper userPlanItemMapper;
    @Autowired
    UserPlanMapper userPlanMapper;

    /**
     * 更新用户学习计划的进度
     *
     * @param planProgressDTO 包含进度更新信息的数据传输对象，包括用户ID、项目引用ID、项目类型和观看时长
     * @return 更新后的用户计划进度对象，如果找不到对应的计划项则返回null
     */
    @Transactional
    @Override
    public UserPlanProgress updatePlanProgress(PlanProgressDTO planProgressDTO) {

        // 查询用户计划项
        LambdaQueryWrapper<UserPlanItem> userPlanItemLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userPlanItemLambdaQueryWrapper.eq(UserPlanItem::getItemIdRef, planProgressDTO.getItemIdRef())
                .eq(UserPlanItem::getItemId, planProgressDTO.getItemType())
                .eq(UserPlanItem::getUserId, planProgressDTO.getUserId());
        UserPlanItem userPlanItem = userPlanItemMapper.selectOne(userPlanItemLambdaQueryWrapper);
        if (userPlanItem == null) {
            return null;
        }
        Long itemId = userPlanItem.getItemId();

        // 查询或创建用户计划进度记录
        LambdaQueryWrapper<UserPlanProgress> userPlanProgressLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userPlanProgressLambdaQueryWrapper.eq(UserPlanProgress::getItemId, itemId)
                .eq(UserPlanProgress::getUserId, planProgressDTO.getUserId());
        UserPlanProgress userPlanProgress = userPlanProgressMapper.selectOne(userPlanProgressLambdaQueryWrapper);
        Long itemDuration = 0L;
        if (userPlanProgress == null) {
            userPlanProgress = new UserPlanProgress();
            userPlanProgress.setUserId(planProgressDTO.getUserId());
            userPlanProgress.setPlanId(userPlanItem.getPlanId());
            userPlanProgress.setItemId(itemId);
            userPlanProgress.setWatchDuration(planProgressDTO.getWatchDuration());
            userPlanProgress.setTotalProgress(0);
            userPlanProgressMapper.insert(userPlanProgress);
        } else {

            // 更新观看时长和计算总进度
            userPlanProgress.setWatchDuration(userPlanProgress.getWatchDuration() + planProgressDTO.getWatchDuration());
            itemDuration = userPlanItem.getItemDuration();
            int progress = (int) (userPlanProgress.getWatchDuration() * 100 / itemDuration);
            if (progress >= 100) {
                progress = 100;
            }
            userPlanProgress.setTotalProgress(progress);
            userPlanProgressMapper.updateById(userPlanProgress);
        }
        // 更新计划项完成时长
        Integer watchDuration = userPlanProgress.getWatchDuration();
        if (watchDuration >= itemDuration) {
            watchDuration = Math.toIntExact(itemDuration);
        }
        userPlanItem.setCompletedDuration(Long.valueOf(watchDuration));
        userPlanItemMapper.updateById(userPlanItem);

        // 更新整个计划的完成情况
        UserPlan userPlan = userPlanMapper.selectById(userPlanItem.getPlanId());
        if (watchDuration >= itemDuration) {
            userPlan.setCompletedDuration((int) (userPlan.getCompletedDuration() + itemDuration));
        }
        if (userPlan.getCompletedDuration() >= userPlan.getTotalDuration() && userPlan.getStatus().equals("0")) {
            UserPlanProgress userPlanProgress1 = new UserPlanProgress();
            userPlanProgress1.setUserId(planProgressDTO.getUserId());
            userPlanProgress1.setPlanId(userPlanItem.getPlanId());
            userPlanProgress1.setWatchDuration(userPlan.getTotalDuration());
            userPlanProgress1.setTotalProgress(100);
            userPlan.setStatus("1");
        }
        userPlanMapper.updateById(userPlan);
        // 更新或创建用户计划进度


        return userPlanProgress;

    }
    
    /**
     * 重置指定计划的进度
     * @param planId 计划ID
     * @param userId 用户ID
     * @return 是否重置成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPlanProgress(Long planId, Long userId) {
        try {
            // 删除该用户指定计划的所有进度记录
            LambdaQueryWrapper<UserPlanProgress> progressWrapper = new LambdaQueryWrapper<>();
            progressWrapper.eq(UserPlanProgress::getPlanId, planId)
                    .eq(UserPlanProgress::getUserId, userId)
                    .isNotNull(UserPlanProgress::getItemId);
            userPlanProgressMapper.delete(progressWrapper);
            
            // 重置该计划下所有项目的完成时长
            LambdaQueryWrapper<UserPlanItem> itemWrapper = new LambdaQueryWrapper<>();
            itemWrapper.eq(UserPlanItem::getPlanId, planId)
                    .eq(UserPlanItem::getUserId, userId);
            UserPlanItem updateItem = new UserPlanItem();
            updateItem.setCompletedDuration(0L);
            userPlanItemMapper.update(updateItem, itemWrapper);
            
            // 重置计划本身的完成状态和时长
            UserPlan userPlan = new UserPlan();
            userPlan.setCompletedDuration(0);
            userPlan.setStatus("0"); // 0表示进行中，1表示已完成
            LambdaQueryWrapper<UserPlan> planWrapper = new LambdaQueryWrapper<>();
            planWrapper.eq(UserPlan::getPlanId, planId)
                    .eq(UserPlan::getUserId, userId);
            userPlanMapper.update(userPlan, planWrapper);
            
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}